from flask_restful import Resource
from comment.model.user import User
from flask import current_app, request
from comment.utils.python_sms_sdk_master.example.SendMessage import send_message
import random
import json
from comment.utils.limiter import limiter as lmt
from . import constants
from flask_limiter.util import get_remote_address
from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser
from comment.utils import parser
from comment.model import db
from comment.utils.tokens_pyjwt import generate_tokens
from comment.utils.decorators import login_required
from flask import g


# 创建一个用户的模块类
class Shopping_User(Resource):
    """
    在get函数上加上登陆拦截
    """
    method_decorators = {
        'get': [login_required],
        'post': [login_required]
    }

    def get(self):  # 测试当前GET函数必须让用户登陆之后才能访问
        current_app.logger.info('我的测试日志')
        return {"hello": "测试"}

    def post(self):
        return {"post": "okpost"}

    def put(self):
        return {"post": "okput"}

    def delete(self):
        return {"post": "okdelete"}


# 发送短信的模块
class User_SMS(Resource):
    """
    发送验证码的短信
    """
    error_message = 'Tom many request'
    decorators = [
        # 三个参数：参数1：限流的速率 参数2：key_func,参数3：如果超出限流之后就有提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,
                  key_func=lambda: request.args['phone'],
                  error_message=error_message),
        lmt.limit(constants.LIMIT_SMS_CODE_BY_IP,
                  # 获取用户的ip地址
                  key_func=get_remote_address,
                  error_message=error_message)
    ]

    def get(self):
        mobile = request.args.get("phone").strip()
        code = random.randint(1000, 9999)
        result = send_message(mobile, str(code))  # 返回的是json的字符串
        result = json.loads(result)  # 把json变成字典
        # result 往里面添加手机号
        result['mobile'] = mobile
        key = 'shopping:code{}'.format(mobile)
        # 短信验证码发送成功后，需要把验证码存放到redis数据库中,方便下次验证,验证码的时效为5分钟
        redis_client.setex(key, constants.SMS_CODE_EXPIRES, code)  # 参数1key,参数2时间
        return result


# 校验手机号的
class AuthorizationCodeResource(Resource):
    """
    提交手机号和验证码，开始验证
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.mobile, required=True)  # required=True这里说的是必须要验证
        rp.add_argument('code', type=parser.regex(r'^\d{4}$'), required=True)
        args = rp.parse_args()
        phone = args.phone
        code = args.code
        # 从之前的redis数据库中得到之前的数据
        key = 'shopping:code{}'.format(phone)
        try:
            real_code = redis_client.get(key)  # 如果没问题那么就从数据库中去拿取数据,拿出来的数据是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {'massage': "redis db connect error."}, 400
        # 开始校验数据
        if not real_code or real_code.decode() != code:
            return {"message": 'Invalid code'}, 400

        return {"phone": phone, "msg": "code success"}, 200


# 注册
class RegisterUserResource(Resource):
    """
    用户注册的界面
    """

    def post(self):
        rp = RequestParser()
        rp.add_argument('phone', type=parser.mobile, required=True)  # required=True这里说的是必须要验证
        rp.add_argument('username', required=True)
        rp.add_argument('password', required=True)
        rp.add_argument('email', type=parser.email, required=True)
        # 从前端页面去获取数据
        args = rp.parse_args()  # 从检验的数据中拿取数据
        username = args.get('username')
        password = args.get('password')
        phone = args.get('phone')
        email = args.get('email')

        # 验证用户名是不是唯一的
        u = User.query.filter(User.username == username).first()
        if u:  # 如果u存在
            current_app.logger.info('{}:用户名已经存在!'.format(username))
            return {"message": "The username already exists!"}, 400  # 用户名已经存在，返回400信息码

        # 把用户名和密码添加到数据库中去
        u = User(username=username, pwd=password, email=email, phone=phone, status=0)  # status这个是指的状态码0是正常1是不正常
        db.session.add(u)
        db.session.commit()
        return {"msg": "OK"}, 200


# 用户登陆模块
class UserLoginResource(Resource):
    """
    登陆
    """

    def post(self):
        """
        登陆只提交用户名和密码，进行校验就行了
        """
        username = request.form.get('username')
        password = request.form.get('password')
        # 判断是否为空
        if not all([username, password]):
            return {"message": "数据不完整"}, 401
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                # 把登陆成功之后的用户ID得到token,token返回给前端
                token = generate_tokens(user.id)
                return {"msg": "Login Success", 'token': token, "username": username}, 200

        return {"message": "用户不存在或者密码错误!"}, 400


# 用户退出登陆
class UserLoginOutResource(Resource):
    """
    退出登陆
    """

    def post(self):
        if g.user_id:  # 如果存在
            g.user_id = None
        return {"msg": "退出成功"}


# 判断手机号是否存在
class IsExistPhoneResource(Resource):
    """
    判断手机号是否存在
    """

    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone == phone).first()
        if user:  # 如果用户有，则表示手机号存在
            return {'isExist': True, 'message': "此手机号已经注册", 'code': 203}
        return {"msg": '手机号可以注册'}
